﻿#ifndef MAINWINDOW_H
#define MAINWINDOW_H

#include <QMainWindow>

#include <QTimer>
#include <QMessageBox>
#include <QThread>
#include <QUrl>
#include <QFile>
#include <QDir>
#include <QPainter>
#include <QtSerialPort/QSerialPortInfo>
#include <QtSerialPort/QSerialPort>
#include <QFileDialog>
#include <QMouseEvent>
#include <QString>
#include <QProgressDialog>

#include "ModbusTcp/ndc_client.h"
#include "Light/light.h"
#include "ImageProcessor/libdmtx0.7.5/dmtx.h"
#include "ImageProcessor/imageprocessor.h"
#include "Calibration/calibration.h"
#include "Camera/camera.h"
#include "RobotArm/robotarm.h"
#include "WorkFlow/workflow.h"

#include "WebAPI/http_client.h"

#pragma execution_character_set("utf-8")

//日志类型
enum class LogType{
    LOG_INFO, //直线运动
    LOG_WARNING,//
    LOG_ERROR//关节运动
};


namespace Ui {
class MainWindow;
}

class MainWindow : public QMainWindow
{
    Q_OBJECT

public:
    explicit MainWindow(QWidget *parent = 0);
    ~MainWindow();

public:
    void SerialPortInit();

    bool calculateCenter();

    bool calculateTransformMatrix();

    bool autoCalibrateImageBoard();

private slots:

    void on_OpenMonitor_clicked();

    void on_closeMonitor_clicked();

    void on_turnOnCamera_clicked();

    void on_turnOffCamera_clicked();

    void timer_getRobotPose();

    void timer_getCameraImage();

    void timer_work_flow_loop();

    void timer_getAGVState();

    void getCameraImage();

    void on_connectButton_clicked();

    void on_readButton_clicked();

    void on_writeButton_clicked();

    void on_startFlowButton_clicked();

    void on_button_moveto_pos_pressed();

    void on_button_moveto_pos_released();

    void on_button_connect_to_robotarm_clicked();

    void on_pushButton_openSerial_clicked();

    void on_pushButton_send_clicked();

    void on_pushButton_openLight_clicked();
    
    void on_pushButton_closeLight_clicked();
    
    void on_pushButton_collision_recover_clicked();

    void on_pushButton_control_log_in_clicked();

    void on_pushButton_control_power_on_clicked();

    void on_pushButton_location_z_down_pressed();

    void on_pushButton_location_z_up_pressed();

    void on_pushButton_location_x_down_pressed();

    void on_pushButton_location_x_up_pressed();

    void on_pushButton_location_y_down_pressed();

    void on_pushButton_location_y_up_pressed();

    void on_pushButton_location_z_down_released();

    void on_pushButton_location_z_up_released();

    void on_pushButton_location_x_down_released();

    void on_pushButton_location_x_up_released();

    void on_pushButton_location_y_down_released();

    void on_pushButton_location_y_up_released();

    void on_pushButton_joint_1_up_pressed();

    void on_pushButton_joint_1_down_pressed();

    void on_pushButton_joint_2_up_pressed();

    void on_pushButton_joint_2_down_pressed();

    void on_pushButton_joint_3_up_pressed();

    void on_pushButton_joint_3_down_pressed();

    void on_pushButton_joint_4_up_pressed();

    void on_pushButton_joint_4_down_pressed();

    void on_pushButton_joint_5_up_pressed();

    void on_pushButton_joint_5_down_pressed();

    void on_pushButton_joint_6_up_pressed();

    void on_pushButton_joint_6_down_pressed();

    void on_pushButton_joint_1_up_released();

    void on_pushButton_joint_1_down_released();

    void on_pushButton_joint_2_up_released();

    void on_pushButton_joint_2_down_released();

    void on_pushButton_joint_3_up_released();

    void on_pushButton_joint_3_down_released();

    void on_pushButton_joint_4_up_released();

    void on_pushButton_joint_4_down_released();

    void on_pushButton_joint_5_up_released();

    void on_pushButton_joint_5_down_released();

    void on_pushButton_joint_6_up_released();

    void on_pushButton_joint_6_down_released();

    void on_pushButton_auto_calibration_clicked();

    void on_pushButton_openCamera_clicked();

    void on_pushButton_closeCamera_clicked();

    void on_pushButton_openLight1_clicked();

    void on_pushButton_closeLight1_clicked();

    void on_pushButton_openLight2_clicked();

    void on_pushButton_closeLight2_clicked();

    void on_pushButton_modbus_write_64_clicked();

    void on_pushButton_modbus_write_65_clicked();

    void on_pushButton_modbus_write_66_clicked();

    void on_horizontalSlider_light1_value_valueChanged(int value);

    void on_horizontalSlider_light2_value_valueChanged(int value);

    void on_spinBox_light1_value_valueChanged(int arg1);

    void on_spinBox_light2_value_valueChanged(int arg1);

    void on_button_add_common_pos_clicked();

    void on_button_load_common_pos_clicked();

    void on_button_save_common_pos_clicked();

    void on_button_delete_common_pos_clicked();
    
    void on_button_moveto_common_pos_pressed();

    void on_button_moveto_common_pos_released();

    void on_button_add_station_pos_clicked();

    void on_button_delete_station_pos_clicked();

    void on_button_moveto_station_pos_released();

    void on_button_load_station_pos_clicked();

    void on_button_save_station_pos_clicked();

    void on_button_moveto_station_pos_pressed();

    void on_comboBox_station_name_pose_currentTextChanged(const QString &arg1);

    void on_pushButton_create_station_clicked();

    void write_stationid_tofile();

    std::set<QString> read_stationid_fromfile();

    void on_comboBox_station_name_currentIndexChanged(int index);

    void on_pushButton_save_calibration_clicked();

    void on_pushButton_load_calibration_clicked();

    void on_comboBox_station_name_matrix_currentIndexChanged(int index);
    
    void on_horizontalSlider_exposure_time_valueChanged(int value);

    void on_pushButton_make_datamtraix_clicked();

    void on_pushButton_save_datamatrix_clicked();

    void on_pushButton_read_image_clicked();

    void on_pushButton_decode_datamatrix_clicked();

    void Initial_encoding_format();

    void dataMatrixDecode();

    void on_pushButton_load_picture_2_clicked();

    void on_pushButton_load_picture_clicked();

    void on_pushButton_detect_QR_clicked();

    void on_pushButton_moveto_QR_clicked();

    void on_pushButton_load_reference_value_clicked();

    void on_pushButton_save_reference_value_clicked();

    void on_stopFlowButton_clicked();

    void on_spinBox_speed_valueChanged(int arg1);

    void on_spinBox_acceleration_valueChanged(int arg1);

    void on_spinBox_deceleration_valueChanged(int arg1);

    void on_button_update_common_pos_clicked();

    void on_button_update_station_pos_clicked();

    void on_pushButton_copy_station_clicked();

    void on_pushButton_U_DO_1_clicked();

    void on_pushButton_U_DO_0_clicked();

    void on_pushButton_U_DI_getstatus_clicked();

    void on_pushButton_openCamera_arm_clicked();

    void on_pushButton_closeCamera_arm_clicked();

    void on_pushButton_load_picture_arm_clicked();

    void on_horizontalSlider_camera_1_exposureTime_valueChanged(int value);

    void on_horizontalSlider_camera_dm_exposureTime_valueChanged(int value);

    void on_pushButton_openCamera_dm_clicked();

    void on_pushButton_closeCamera_dm_clicked();

    void on_pushButton_capture_image_dm_clicked();

    //Test1-Step1: 等待取生料请求信号
    void on_pushButton_T1_S1_clicked();
    //Test1-Step2: 移动到取生料点前方
    void on_pushButton_T1_S2_clicked();
    //Test1-Step3: 等待转移平台允许信号
    void on_pushButton_T1_S3_clicked();
    //Test1-Step4: 移动到取生料位
    void on_pushButton_T1_S4_clicked();
    //Test1-Step5: 吸料
    void on_pushButton_T1_S5_clicked();
    //Test1-Step6: 移动到二次平台上方

    //Test1-Step7: 吹料
    void on_pushButton_T1_S7_clicked();
    //Test1-Step8: 识别产品DM码
    void on_pushButton_T1_S8_clicked();
    //Test1-Step9: 移动回待机点
    void on_pushButton_T1_S9_clicked();
    //Test1-Step10: 给转移平台允许转移信号
    void on_pushButton_T1_S10_clicked();

    /* Test 2*/
    //Test2-Step1: 等待取料请求信号
    void on_pushButton_T2_S1_clicked();
    //Test2-Step2: 移动到视觉拍照位
    void on_pushButton_T2_S2_clicked();
    //Test2-Step3: 视觉定位
    void on_pushButton_T2_S3_clicked();
    //Test2-Step4: 移动到CNC机台门口
    void on_pushButton_T2_S4_clicked();
    //Test2-Step5: 等待开门信号
    void on_pushButton_T2_S5_clicked();
    //Test2-Step6: 移动到CNC机台OK料位
    void on_pushButton_T2_S6_clicked();
    //Test2-Step7: 吸料
    void on_pushButton_T2_S7_clicked();
    //Test2-Step8: 移动到放OK料前方
    void on_pushButton_T2_S8_clicked();
    //Test2-Step9: 等待转移平台允许信号
    void on_pushButton_T2_S9_clicked();
    //Test2-Step10: 移动到转移平台OK位
    void on_pushButton_T2_S10_clicked();
    //Test2-Step11: 吹料
    void on_pushButton_T2_S11_clicked();
    //Test2-Step12: 移动回待机点
    void on_pushButton_T2_S12_clicked();
    //Test2-Step13: 给转移平台允许转移信号
    void on_pushButton_T2_S13_clicked();
    //Test2-Step14: 给AGV取料完成信号
    void on_pushButton_T2_S14_clicked();


    /* Test-3 */
    //Test3-Step1: 等待放料请求信号
    void on_pushButton_T3_S1_clicked();
    //Test3-Step2: 移动到视觉拍照位
    void on_pushButton_T3_S2_clicked();
    //Test3-Step3: 视觉定位
    void on_pushButton_T3_S3_clicked();
    //Test3-Step4: 移动到二次定位平台
    void on_pushButton_T3_S4_clicked();
    //Test3-Step5: 吸料
    void on_pushButton_T3_S5_clicked();
    //Test3-Step6: 移动到CNC机台门口
    void on_pushButton_T3_S6_clicked();
    //Test3-Step7: 等待开门信号
    void on_pushButton_T3_S7_clicked();
    //Test3-Step8: 移动到CNC机台OK料位
    void on_pushButton_T3_S8_clicked();
    //Test3-Step9: 吹料
    void on_pushButton_T3_S9_clicked();
    //Test3-Step10: 移动回待机点
    void on_pushButton_T3_S10_clicked();
    //Test3-Step11: 给AGV放料完成信号
    void on_pushButton_T3_S11_clicked();

    void on_pushButton_T3_S12_clicked();

    void on_pushButton_add_rotation_pose_clicked();

    void on_pushButton_find_center_clicked();

    void on_pushButton_draw_model_clicked();

    void on_pushButton_create_model_clicked();

    void on_pushButton_match_model_clicked();

    void on_button_load_station_template_info_clicked();

    void on_pushButton_rotate_fixed_angle_pressed();

    void on_pushButton_rotate_fixed_angle_released();

    void on_pushButton_set_reference_pose_clicked();

    void on_pushButton_moveto_reference_pose_pressed();

    void on_pushButton_moveto_reference_pose_released();

    void on_pushButton_match_reference_pose_clicked();

    void on_pushButton_openCamera_arm_continue_clicked();

    void on_tableWidget_autoCalibration_activated(const QModelIndex &index);

    void on_pushButton_correct_base_pose_clicked();

    void on_pushButton_moveto_base_pose_pressed();

    void on_pushButton_moveto_base_pose_released();

    void on_pushButton_T1_S6_clicked();

    void on_pushButton_modbus_write_67_clicked();


    //任务细分

    //生料为raw，加工完成为workpiece

    /*****************
          等待信号
    ******************/

    //等待取生料请求信号,放到二次定位平台
    bool waitfor_taking_raw_signal(int time);
    //等待取加工料请求信号
    bool waitfor_taking_workpiece_signal(int time);
    //等待转移平台允许信号
    bool waitfor_transfer_allowing_signal(int time);
    //等待开门信号(光电检测是否已经开门),检测到开门之后还要等几秒
    bool waitfor_opening_CNC_door(int time);
    //等待放料请求信号（放料时的开门信号）
    bool waitfor_putting_raw_signal(int time);

    /*****************
          发送信号
    ******************/

    //给转移平台允许转移信号
    bool send_transfer_allowing_signal();
    //给AGV取料完成信号
    bool send_finishing_taking_signal();
    //给AGV放料完成信号
    bool send_finishing_putting_signal();
    //上传DM码信心
    bool send_dm_message(QString dm_mmessage, int outtime);


    /*****************
         机械臂移动任务
    ******************/

    //从待机点，移动到转移平台前方，（不分左右）
    bool moveto_transfer_front_pose_from_initialpose();
    //从转移平台前方，移动到取生料位，（不分左右）
    bool moveto_tranferplane_pose();
    //从转移平台前方，移动到放熟料位，（不分左右）
    bool moveto_tranferplane_unload_pose();


    //从取生料位，移动到二次定位平台上方,（不分左右）
    bool moveto_locationplane_pose_above_from_transfer();
    //从二次平台上方，移动到吹DM码上方（不分左右）
    bool moveto_chowing_DMcode_pose_above();
    //从二次定位平台，移动回待机点（不分左右）
    bool moveto_initialpose_from_locationplane();
    //上下移动并清洗（不分左右）
    bool move_upanddown();
    //从水槽，移动到放OK料前方（同取生料位上方）（不分左右）
    bool moveto_transfer_front_pose_from_waterpool();
    //从转移平台取放料点，移动到带基点
    bool moveto_initialpose_from_transfer();


    //从待机点，移动到视觉拍照位(分左右)
    bool moveto_taking_image_pose();
    //从视觉定位处，移动到CNC机台门口（分左右）
    bool moveto_CNC_front_door_from_visionpose();
    //从机台门口，移动到CNC机台OK料位（可能分左右）
    bool moveto_CNC_baseplane_taking_pose();

    //从机台门口，移动到CNC机台OK料位（可能分左右）
    bool moveto_CNC_baseplane_putting_pose();

    //从CNC机台，移动到水槽（分左右）
    bool moveto_waterpool();
    //从视觉定位处，移动到二次定位平台(分左右)
    bool moveto_locationplane_pose_from_visionpose();
    //从二次定位平台，移动到CNC机台门口（分左右）
    bool moveto_CNC_front_door_from_locationplane();
    //从CNC机台，移动回待机点（分左右）
    bool moveto_initialpose_from_CNC();
    //移动到丢废料点
    bool moveto_discard_unused();



    /****************************
         空压机、真空泵、抽水泵动作
    ****************************/

    //吸料
    bool suck_workpiece();
    //吹料
    bool chow_workpiece();
    //吹气n秒
    bool chow_only(int time);

    //吹产品DM码
    bool chow_DMcode();
    //打开抽水泵
    bool start_washing_workpiece();
    //关闭抽水泵
    bool close_washing_workpiece();
    //闭合小夹爪
    bool close_jaw();
    //松开小夹爪
    bool open_jaw();


    /*****************
         视觉处理
    ******************/

    //视觉定位
    bool process_image_and_correct_pose();
    //读DM码
    bool decode_DMcode();


    /*****************
         异常流程处理
    ******************/

    //在转移平台取生料异常
    bool exception_when_taking_raw_at_transfer();
    //在二次定位平台取生料异常
    bool exception_when_taking_raw_at_localization();
    //视觉拍照异常
    bool exception_when_processing_vision();
    //取熟料异常
    bool exception_when_taking_workpiece();
    //
    bool stop_work_flow();
    //机台门打开异常
    bool exception_when_opening_door();
    //当机台无熟料时
    bool exception_when_no_workpiece_in_CNC();


    /*****************
         初始化加载函数
    ******************/

    //连接机械臂
    bool connect_to_robotarm();
    //加载机械臂公共点
    bool load_common_pos();
    //加载机械臂机台点
    bool load_station_pos();
    //打开光源串口
    bool openSerial();
    //打开机械臂相机
    bool openCamera_arm();
    //加载标定数据
    bool load_calibration();
    //连接modbus服务器
    bool openModbus();
    //打开读Dm码相机
    bool openCamera_dm();
    //加载模板长宽信息
    bool load_station_template_info();
    //加载机台二维码信息
    bool load_station_qr_info();


    void on_pushButton_T1_S11_clicked();

    void on_pushButton_T2_S15_clicked();

    void on_pushButton_T2_S16_clicked();

    void on_pushButton_T2_S17_clicked();

    void on_spinBox_joint_speed_valueChanged(int arg1);

    void on_spinBox_joint_acceleration_valueChanged(int arg1);

    void on_spinBox_joint_deceleration_valueChanged(int arg1);

    void on_pushButton_modbus_write_68_clicked();

    void on_button_load_all_station_data_clicked();

    void on_button_stop_reading_dm_clicked();

    void on_radioButton_speed_medium_clicked();

    void on_radioButton_speed_low_clicked();

    void on_radioButton_speed_fast_clicked();

    void log_message(LogType type, QString message);

    void on_button_move_by_path_clicked();

    void on_button_stop_test_clicked();

    //原先模式
    void run_all_work_flow();
    //运行状态机模式
    void run_statemachine_flow();

    void on_pushButton_T3_S8_2_clicked();

    void on_pushButton_get_station_state_clicked();

    void on_pushButton_bind_station_qr_clicked();

    void on_pushButton_load_station_qr_clicked();

    void on_comboBox_station_name_qr_currentIndexChanged(int index);

    void on_pushButton_open_station_door_clicked();

    void on_pushButton_close_station_door_clicked();

    void on_pushButton_wash_CNC_station_clicked();

    void on_button_refine_station_pos_clicked();

    //运行流程
    void run_step_0();
    void run_step_1();
    void run_step_2();
    void run_step_3();
    void run_step_4();
    void run_step_5();
    void run_step_6();
    void run_step_7();
    void run_step_8();
    void run_step_9();
    void run_step_10();
    void run_step_11();
    void run_step_12();
    void run_step_13();
    void run_step_14();
    void run_step_15();
    void run_step_16();
    void run_step_17();
    void run_step_18();
    void run_step_19();
    void run_step_20();
    void run_step_21();
    void run_step_22();
    void run_step_23();
    void run_step_24();
    void run_step_25();
    void run_step_26();
    void run_step_27();
    void run_step_28();
    void run_step_29();
    void run_step_30();
    void run_step_31();
    void run_step_32();
    void run_step_33();

    void on_pauseFlowButton_clicked();

    void on_checkBox_obstacle_stateChanged(int arg1);

signals:
    void sig_dowork();
    void sig_start_monitor();

public slots:
    void slot_finish();

protected:
    void mousePressEvent(QMouseEvent *event);
    void mouseMoveEvent(QMouseEvent *event);
    void mouseReleaseEvent(QMouseEvent *event);
    bool eventFilter(QObject *watched, QEvent *event);
    void wheelEvent(QWheelEvent *event) ;
    void resizeEvent(QResizeEvent *event) ;
    void changeWheelValue(QPoint event,int value);

private:
   void mkdir_ifneed(QString dir);

  void set_test_state(QString testName, int step_index, bool state);
  bool check_test_state(QString testName, int step_index);
  void set_test_qlabel();

  void sleep_ms(int msecond);

  void upPaint();

  bool get_image_and_match(QString station_id,
                           cv::Point2d& center,
                           float& angle);

  void initial_station_mapper();

private:
    Ui::MainWindow *ui;

    Camera* camera_;
    RobotArm* mainthread_robot_arm_;
    RobotArmMonitor* robot_arm_monitor_;
    ImageProcessor image_processor_;
    Calibration calibration_;
    //ClientStation client_station_;
    //ModbusTcp modbus_tcp_;
    //modbus* modbus_tcp_;
    NDC_Client NDC_Client_;

    Light* light_;

    WorkFlow* work_flow_;
    QThread* work_flow_pthread_;
    QThread* robot_monitor_thread_;

    std::vector<cv::Point2d> originPointsRobot;

    QTimer* timer_get_robot_pose_;
    QTimer* timer_get_camera_image_;
    QTimer* timer_work_flow_;
    QTimer* timer_get_agv_state_;

    std::set<QString> station_ids;

    //DataMatrix
    QImage globalImg;//存储图片用
    QImage globalImg2;//存储图片用
    QString globastr;//保存str信息
    cv::Mat QR_image;
    QImage  qcolorshow;//显示图像用

    int test1_step_state[12]; // index 0 do not use
    int test2_step_state[18]; // index 0 do not use
    int test3_step_state[13]; // index 0 do not use

    QLabel * test1_qlabel[12]; //test2 qlabel;
    QLabel * test2_qlabel[18]; //test2 qlabel;
    QLabel * test3_qlabel[13]; //test2 qlabel;

    cv::Mat Dm_image;

    //bool
    //触发框选
    bool isPressed;
    bool rectFlag = false;
    //框选矩形框
    //0-x 1-y 2-width 3-height
    int rect[4] = {0};
    CONST int offset = 60;

    //放大缩小平移qlabel
    double m_scaleValue = 1.0;      // 图片缩放倍数
    QPointF m_drawPoint = QPointF(0,0);     // 绘图起点
    QPointF m_mousePoint = QPointF(0,0);   // 鼠标当前位置点
    QRect m_rectPixmap = QRect(0,0,0,0);       // 被绘图片的矩形范围
    bool m_isMousePress = false;      // 鼠标是否按下

    const double SCALE_MAX_VALUE=10.0;//最大放大到原来的10倍
    const double SCALE_MIN_VALUE=0.5;//最小缩小到原来的0.5倍

    //
    std::vector<cv::Point2d> fitting_circle_points;
    std::vector<cv::Point2d> center_nine_points;

    cv::Point2d current_match_center;
    float current_match_angle;
    RobotPoseXYZ station_correct_pose;
    QString current_station_id;

    RobotPoseXYZ station_correct_discard_pose;

    //
    //DataMatrix码信息
    QString DM_msg;

    bool has_workpeice_in_localization = false;

    //直线运动通用速度
    double LineSpeed = 30;
    int LineACC = 30;
    int LineDEC = 30;

    //关节运动通用速度
    double JointSpeed = 5;
    int JointACC = 5;
    int JointDEC = 5;

    //停止继续扫码， 结束流程
    bool stop_reading_dm = false;
    int image_count = 0;

    //第一次真空检测
    bool first_check_sucking = false;

    QTime totalTime;
    QTime stepTime;

    HTTP_client http_client_;

    //绑定机台号和机台二维码
    std::map<QString,QString> station_id_mapper;

    //DM_code
    std::string dm_message;

    //流程状态
    bool work_flag = false;

    //存储当前步骤
    int current_step = 0;

    //接近开关检测有物料
    int check_by_BERO = 0;

    //检测到避障状态
    bool obstacle_state = false;
    //避障超时
    QTime obstacle_outTime;

};

#endif // MAINWINDOW_H
